package com.xnyzc.lhy.mis.service.impl.cms.user.wallet;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xnyzc.lhy.common.component.convert.DateToStringConverter;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.EOrderType;
import com.xnyzc.lhy.common.penum.amount.EAmountType;
import com.xnyzc.lhy.common.penum.dept.EOffIceType;
import com.xnyzc.lhy.common.penum.pay.ETransactionOrderNoType;
import com.xnyzc.lhy.common.penum.push.EJPushBalanceChangeType;
import com.xnyzc.lhy.common.penum.wallet.EIsTransaction;
import com.xnyzc.lhy.common.penum.wallet.ERecordType;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.common.util.IDUtil;
import com.xnyzc.lhy.mis.entity.util.OrderUtil;
import com.xnyzc.lhy.mis.mapper.dictionaries.OaSysDictMapper;
import com.xnyzc.lhy.mis.mapper.sidebar.OaCUserOfficeMapper;
import com.xnyzc.lhy.mis.mapper.sidebar.OaSysOfficeMapper;
import com.xnyzc.lhy.mis.mapper.user.OaCUserMapper;
import com.xnyzc.lhy.mis.mapper.user.wallet.OaCWalletMapper;
import com.xnyzc.lhy.mis.mapper.user.wallet.OaCWalletRecordMapper;
import com.xnyzc.lhy.mis.service.cms.user.wallet.IOaSysUserWalletService;
import com.xnyzc.lhy.mis.service.cms.util.IOaSysGetOfficeIdListService;
import com.xnyzc.lhy.mis.util.service.JPushBalanceChangeUtilService;
import com.xnyzc.lhy.mis.entity.dictionaries.OaSysDict;
import com.xnyzc.lhy.mis.entity.sidebar.OaCUserOffice;
import com.xnyzc.lhy.mis.entity.sidebar.OaSysOffice;
import com.xnyzc.lhy.mis.entity.user.OaCUser;
import com.xnyzc.lhy.mis.entity.user.wallet.OaCWallet;
import com.xnyzc.lhy.mis.entity.user.wallet.OaCWalletRecord;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description 后台用户钱包管理
 * @Author zhuyubin
 * @Date 2019-08-20 16:00
 **/
@Service
public class OaSysUserWalletServiceImpl implements IOaSysUserWalletService {

    @Autowired
    private IOaSysGetOfficeIdListService iOaSysGetOfficeIdListService;
    @Autowired
    private OaCWalletMapper oaCWalletMapper;
    @Autowired
    private OaCUserMapper oaCUserMapper;
    @Autowired
    private OaCWalletRecordMapper oaCWalletRecordMapper;
    @Autowired
    private OaCUserOfficeMapper oaCUserOfficeMapper;
    @Autowired
    private OaSysOfficeMapper oaSysOfficeMapper;
    @Autowired
    private OaSysDictMapper oaSysDictMapper;
    @Autowired
    private JPushBalanceChangeUtilService jPushBalanceChangeUtilService;

    /**
     * 获取用户钱包记录
     * @param userId 用户id
     * @param type 权限等级
     * @param tag 租户
     * @param current 当前页
     * @param name 用户名
     * @param phone 手机号
     * @return
     */
    @Override
    public IPage<Map<String, Object>> seleceOaSysUserWallet(Long userId, List<String> type, String tag, Long current, String name, String phone, Long officeId){
        // 可查看部门
        List<Long> officeIds = iOaSysGetOfficeIdListService.selectOfficeIdList(userId);
        List<OaSysOffice> offices = oaSysOfficeMapper.selectList(Wrappers.<OaSysOffice>lambdaQuery().eq(OaSysOffice::getTag, tag).in(OaSysOffice::getOfficeId, officeIds));
        List<Long> userIds = iOaSysGetOfficeIdListService.selectCUserIdList(userId, type);
        LambdaQueryWrapper<OaCUser> oaCUserLambdaQW = Wrappers.<OaCUser>lambdaQuery()
                .eq(OaCUser::getTag, tag)
                .in(OaCUser::getUserId, userIds);
        if (CheckUtil.objIsNotEmpty(phone)){
            oaCUserLambdaQW.like(OaCUser::getUserPhone, phone);
        }
        if (CheckUtil.objIsNotEmpty(name)){
            oaCUserLambdaQW.like(OaCUser::getUserName, name);
        }
        userIds = new ArrayList<>();
        List<OaCUser> oaCUserList = oaCUserMapper.selectList(oaCUserLambdaQW);
        for (OaCUser oaCUser : oaCUserList) {
            userIds.add(oaCUser.getUserId());
        }
        if (CheckUtil.objIsEmpty(userIds)){
            userIds.add(-1L);
        }
        if (CheckUtil.objIsNotEmpty(officeId)){
            LambdaQueryWrapper<OaCUserOffice> oaCUserOfficeLQW = Wrappers.<OaCUserOffice>lambdaQuery()
                    .eq(OaCUserOffice::getTag, tag)
                    .in(OaCUserOffice::getUserId, userIds);
            List<OaSysOffice> oaSysOffices = oaSysOfficeMapper.selectList(
                    Wrappers.<OaSysOffice>lambdaQuery()
                            .eq(OaSysOffice::getTag, tag)
                            .eq(OaSysOffice::getParentId, officeId)
                            .in(OaSysOffice::getOfficeId, officeIds));
            // 公司
            if (oaSysOffices.size() > 0){
                List<Long> deptIds = new ArrayList<>();
                for (OaSysOffice oaSysOffice : oaSysOffices) {
                    if (EOffIceType.dept.getValue().equals(oaSysOffice.getType())){
                        deptIds.add(oaSysOffice.getOfficeId());
                    }
                }
                if (CheckUtil.objIsEmpty(deptIds)){
                    deptIds.add(-1L);
                }
                oaCUserOfficeLQW.in(OaCUserOffice::getOfficeId, deptIds);
            }
            // 部门
            else {
                oaCUserOfficeLQW.eq(OaCUserOffice::getOfficeId, officeId);
            }
            List<OaCUserOffice> oaCUserOffices = oaCUserOfficeMapper.selectList(oaCUserOfficeLQW);
            userIds = new ArrayList<>();
            for (OaCUserOffice oaCUserOffice : oaCUserOffices) {
                userIds.add(oaCUserOffice.getUserId());
            }
            if (CheckUtil.objIsEmpty(userIds)){
                userIds.add(-1L);
            }
        }
        Page<OaCWallet> oaCWalletPage = new Page<>();
        oaCWalletPage.setCurrent(current);
        oaCWalletPage.setSize(20L);
        IPage<OaCWallet> oaCWalletIPage = oaCWalletMapper.selectPage(oaCWalletPage,
                Wrappers.<OaCWallet>lambdaQuery()
                        .eq(OaCWallet::getTag, tag)
                        .in(OaCWallet::getUserId, userIds)
                        .orderByDesc(OaCWallet::getCreateTime)
        );
        List<Map<String, Object>> list = new ArrayList<>();
        List<Long> userIdsList = new ArrayList<>();
        for (OaCWallet oaCWallet : oaCWalletIPage.getRecords()) {
            Map<String, Object> map = new HashMap<>(16);
            map.put("walletBalance", oaCWallet.getWalletBalance());
            map.put("personalOfficialBalance", oaCWallet.getPersonalOfficialBalance());
            map.put("deptOfficialBalance", oaCWallet.getDeptOfficialBalance());
            map.put("isPersonalAmount", oaCWallet.getIsPersonalAmount());
            map.put("isDeptAmount", oaCWallet.getIsDeptAmount());
            map.put("userId", oaCWallet.getUserId());
            userIdsList.add(oaCWallet.getUserId());
            map.put("name", "");
            map.put("phone", "");
            map.put("officeName", "");
            map.put("parentId", "");
            list.add(map);
        }
        List<OaCUser> oaCUsers = oaCUserMapper.selectList(Wrappers.<OaCUser>lambdaQuery().eq(OaCUser::getTag, tag).in(OaCUser::getUserId, userIds));
        List<OaCUserOffice> oaCUserOffices = oaCUserOfficeMapper.selectList(Wrappers.<OaCUserOffice>lambdaQuery().eq(OaCUserOffice::getTag, tag).in(OaCUserOffice::getUserId, userIds));
        List<Map<String, Object>> result = new ArrayList<>();
        for (Map<String, Object> map : list) {
            String userid = "-1";
            // 增加基本信息
            for (OaCUser oaCUser : oaCUsers) {
                userid = map.get("userId").toString();
                if (oaCUser.getUserId().equals(Long.valueOf(userid))){
                    map.put("name", oaCUser.getUserName());
                    map.put("phone", oaCUser.getUserPhone());
                }
            }
            // 增加部门
            for (OaCUserOffice oaCUserOffice : oaCUserOffices) {
                if (oaCUserOffice.getUserId().equals(Long.valueOf(userid))){
                    map.put("officeId", oaCUserOffice.getOfficeId());
                }
            }
            for (OaSysOffice office : offices) {
                if (CheckUtil.objIsEmpty(map.get("officeId"))){
                    continue;
                }
                if (office.getOfficeId().equals(Long.valueOf(map.get("officeId").toString()))){
                    map.put("officeName", office.getName());
                    map.put("parentId", office.getParentId());
                }
            }
            // 增加公司
            for (OaSysOffice office : offices) {
                Object parentId = map.get("parentId");
                if (CheckUtil.objIsEmpty(parentId, office.getOfficeId())){
                    continue;
                }
                if (office.getOfficeId().equals(Long.valueOf(parentId.toString()))){
                    map.put("parentName", office.getName());
                }
            }
            result.add(map);
        }
        IPage<Map<String, Object>> page = new Page<>();
        page.setPages(oaCWalletIPage.getPages());
        page.setRecords(result);
        page.setTotal(oaCWalletIPage.getTotal());
        page.setSize(oaCWalletIPage.getSize());
        page.setCurrent(current);
        return page;
    }

    /**
     * 更新额度开关
     * @param sysUserId 操作人id
     * @param userIds 用户id
     * @param type 额度类型0个人额度1部门额度2余额
     * @param switchType 修改状态
     * @param tag 租户
     * @return
     */
    @Override
    public String updateSwitch(Long sysUserId, List<Long> userIds, Integer type, Integer switchType, String tag){
        for (Long userId : userIds) {
            OaCWallet oaCWallet = oaCWalletMapper.selectOne(
                    Wrappers.<OaCWallet>lambdaQuery()
                            .eq(OaCWallet::getTag, tag)
                            .eq(OaCWallet::getUserId, userId)
            );
            if (CheckUtil.objIsEmpty(oaCWallet)){
                throw PangException.create(EErrorCode.unWallet);
            }
            if (EAmountType.personalAmount.getValue().equals(type)){
                oaCWallet.setIsPersonalAmount(switchType);
                oaCWallet.setUpdateUser(sysUserId);
                oaCWallet.setUpdateTime(new Date());
            } else {
                oaCWallet.setIsDeptAmount(switchType);
                oaCWallet.setUpdateUser(sysUserId);
                oaCWallet.setUpdateTime(new Date());
            }
            int i = oaCWalletMapper.updateById(oaCWallet);
            if (i != 1){
                throw PangException.create(EErrorCode.updateWalletFailure);
            }
        }
        return EErrorCode.updateWalletSuccess.getDesc();
    }

    /**
     * 更新充值
     * @param sysUserId 操作人id
     * @param userIds 用户id
     * @param tag 租户
     * @param type 类型
     * @param money 金额
     * @return
     */
    @Override
    public String updateMoney(Long sysUserId, List<Long> userIds, String tag, Integer type, BigDecimal money){
        for (Long userId : userIds) {
            OaCWallet oaCWallet = oaCWalletMapper.selectOne(Wrappers.<OaCWallet>lambdaQuery().eq(OaCWallet::getTag, tag).eq(OaCWallet::getUserId, userId));
            if (CheckUtil.objIsEmpty(oaCWallet)){
                throw PangException.create(EErrorCode.unWallet);
            }
            // 个人额度
            if (EAmountType.personalAmount.getValue().equals(type)){
                oaCWallet.setPersonalOfficialBalance(oaCWallet.getPersonalOfficialBalance().add(money));
                oaCWallet.setUpdateUser(sysUserId);
                oaCWallet.setUpdateTime(new Date());
            }
            // 部门额度
            else if (EAmountType.officeAmount.getValue().equals(type)){
                oaCWallet.setDeptOfficialBalance(oaCWallet.getDeptOfficialBalance().add(money));
                oaCWallet.setUpdateUser(sysUserId);
                oaCWallet.setUpdateTime(new Date());
            }
            // 余额
            else {
                oaCWallet.setWalletBalance(oaCWallet.getWalletBalance().add(money));
                oaCWallet.setUpdateUser(sysUserId);
                oaCWallet.setUpdateTime(new Date());
            }
            int i = oaCWalletMapper.updateById(oaCWallet);
            if (i != 1){
                throw PangException.create(EErrorCode.rechargeSuccess);
            }
            OaCWalletRecord oaCWalletRecord = new OaCWalletRecord();
            Long recordId = IDUtil.nextId();
            oaCWalletRecord.setRecordId(recordId);
            oaCWalletRecord.setUserId(userId);
            // 个人
            if (EAmountType.personalAmount.getValue().equals(type)){
                oaCWalletRecord.setOrderNo(OrderUtil.orderNo(EOrderType.TEGR));
                oaCWalletRecord.setRecordType(ERecordType.myTopUp.getType());
                oaCWalletRecord.setTransactionOrderNo(OrderUtil.transactionOrderNo(ETransactionOrderNoType.personalBusiness));
            }
            // 部门
            else if (EAmountType.officeAmount.getValue().equals(type)){
                oaCWalletRecord.setOrderNo(OrderUtil.orderNo(EOrderType.TEGW));
                oaCWalletRecord.setRecordType(ERecordType.officialTopUp.getType());
                oaCWalletRecord.setTransactionOrderNo(OrderUtil.transactionOrderNo(ETransactionOrderNoType.deptService));
            }
            // 余额
            else {
                oaCWalletRecord.setOrderNo(OrderUtil.orderNo(EOrderType.CZYE));
                oaCWalletRecord.setRecordType(ERecordType.moneyTopUp.getType());
                oaCWalletRecord.setTransactionOrderNo(OrderUtil.transactionOrderNo(ETransactionOrderNoType.balancePay));
            }
            oaCWalletRecord.setActualAmount(money);
            oaCWalletRecord.setIsTransaction(EIsTransaction.paySuccess.getValue());
            oaCWalletRecord.setTransactionTime(new Date());
            oaCWalletRecord.setTag(tag);
            oaCWalletRecord.setWalletBalance(oaCWallet.getWalletBalance());
            oaCWalletRecord.setPersonalOfficialBalance(oaCWallet.getPersonalOfficialBalance());
            oaCWalletRecord.setDeptOfficialBalance(oaCWallet.getDeptOfficialBalance());
            oaCWalletRecord.setCreateUser(userId);
            oaCWalletRecord.setCreateTime(new Date());
            oaCWalletRecord.setUpdateUser(userId);
            oaCWalletRecord.setUpdateTime(new Date());
            i = oaCWalletRecordMapper.insert(oaCWalletRecord);
            if (i != 1){
                throw PangException.create(EErrorCode.rechargeFailure);
            }
            // 极光推送 余额变更
            if (EAmountType.balance.getValue().equals(type)){
                jPushBalanceChangeUtilService.passengerPush(userId, tag, EJPushBalanceChangeType.recharge.getValue(), recordId, money);
            }
        }
        return EErrorCode.rechargeSuccess.getDesc();
    }

    /**
     * 获取用户钱包
     * @param sysUserId 后台用户
     * @param type 等级
     * @param current 当前页
     * @param tag 租户
     * @param name 姓名
     * @return
     */
    @Override
    public IPage<Map<String, Object>> selectUserWalletRecordPage(Long sysUserId, List<String> type, Long current, Long size, String tag, String name, String phone, String orderNo, Integer recordType){
        // 可查看用户
        List<Long> userIds = iOaSysGetOfficeIdListService.selectCUserIdList(sysUserId, type);
        LambdaQueryWrapper<OaCUser> oaCUserLambdaQW = Wrappers.<OaCUser>lambdaQuery()
                .eq(OaCUser::getTag, tag)
                .in(OaCUser::getUserId, userIds);
        if (CheckUtil.objIsNotEmpty(phone)){
            oaCUserLambdaQW.like(OaCUser::getUserPhone, phone);
        }
        if (CheckUtil.objIsNotEmpty(name)){
            oaCUserLambdaQW.like(OaCUser::getUserName, name);
        }
        userIds = new ArrayList<>();
        List<OaCUser> userList = oaCUserMapper.selectList(oaCUserLambdaQW);
        for (OaCUser user : userList) {
            userIds.add(user.getUserId());
        }
        if (CheckUtil.objIsEmpty(userIds)){
            userIds.add(-1L);
        }
        IPage<OaCWalletRecord> oaCWalletRecordIPage = new Page<>();
        oaCWalletRecordIPage.setCurrent(current);
        oaCWalletRecordIPage.setSize(20L);
        if (CheckUtil.objIsNotEmpty(size)){
            oaCWalletRecordIPage.setSize(size);
        }
        LambdaQueryWrapper<OaCWalletRecord> oaCWalletRecordLambdaQW = Wrappers.<OaCWalletRecord>lambdaQuery()
                .eq(OaCWalletRecord::getTag, tag)
                .in(OaCWalletRecord::getUserId, userIds)
                .orderByDesc(OaCWalletRecord::getCreateTime);
        if (CheckUtil.objIsNotEmpty(recordType)){
            oaCWalletRecordLambdaQW.eq(OaCWalletRecord::getRecordType, recordType);
        }
        if (CheckUtil.objIsNotEmpty(orderNo)){
            oaCWalletRecordLambdaQW.like(OaCWalletRecord::getOrderNo, orderNo);
        }
        oaCWalletRecordIPage = oaCWalletRecordMapper.selectPage(oaCWalletRecordIPage, oaCWalletRecordLambdaQW);
        userIds = new ArrayList<>();
        List<Map<String, Object>> list = new ArrayList<>();
        for (OaCWalletRecord oaCWalletRecord : oaCWalletRecordIPage.getRecords()) {
            Map<String, Object> map = new HashMap<>(16);
            Long userId = oaCWalletRecord.getUserId();
            userIds.add(userId);
            map.put("recordId", oaCWalletRecord.getRecordId());
            map.put("userId", oaCWalletRecord.getUserId());
            map.put("name", "");
            map.put("phone", "");
            map.put("officeId", "");
            map.put("officeName", "");
            map.put("parentId", "");
            map.put("parentName", "");
            map.put("orderNo", oaCWalletRecord.getOrderNo());
            map.put("actualAmount", CheckUtil.objIsEmpty(oaCWalletRecord.getActualAmount()) ? "" : oaCWalletRecord.getActualAmount().toString());
            map.put("recordType", CheckUtil.objIsEmpty(oaCWalletRecord.getRecordType()) ? "" : ERecordType.findById(oaCWalletRecord.getRecordType()).getValue());
            map.put("isTransaction", CheckUtil.objIsEmpty(oaCWalletRecord.getIsTransaction()) ? "" : EIsTransaction.findById(oaCWalletRecord.getIsTransaction()).getDesc());
            map.put("transactionTime", CheckUtil.objIsEmpty(oaCWalletRecord.getTransactionTime()) ? "" : new DateToStringConverter().convert(oaCWalletRecord.getTransactionTime()));
            list.add(map);
        }
        List<OaCUser> users = oaCUserMapper.selectList(Wrappers.<OaCUser>lambdaQuery().eq(OaCUser::getTag, tag).in(OaCUser::getUserId, userIds));
        // 可查看部门
        List<Long> officeIds = iOaSysGetOfficeIdListService.selectOfficeIdList(sysUserId);
        // 用户部门关联
        List<OaCUserOffice> oaCUserOfficeList = oaCUserOfficeMapper.selectList(Wrappers.<OaCUserOffice>lambdaQuery().eq(OaCUserOffice::getTag, tag).in(OaCUserOffice::getOfficeId, officeIds));
        // 部门
        List<OaSysOffice> offices = oaSysOfficeMapper.selectList(Wrappers.<OaSysOffice>lambdaQuery().eq(OaSysOffice::getTag, tag).in(OaSysOffice::getOfficeId, officeIds));
        List<Map<String, Object>> result = new ArrayList<>();
        for (Map<String, Object> map : list) {
            // 添加基本信息
            for (OaCUser oaCUser : users) {
                Object userId = map.get("userId");
                if (oaCUser.getUserId().equals(userId)){
                    map.put("name", oaCUser.getUserName());
                    map.put("phone", oaCUser.getUserPhone());
                }
            }
            // 新增部门id
            for (OaCUserOffice oaCUserOffice : oaCUserOfficeList) {
                map.put("officeId", oaCUserOffice.getOfficeId());
            }
            // 新增部门信息
            for (OaSysOffice office : offices) {
                Object officeId = map.get("officeId");
                if (CheckUtil.objIsEmpty(officeId)){
                    continue;
                }
                if (office.getOfficeId().equals(Long.valueOf(officeId.toString()))){
                    map.put("officeName", office.getName());
                    map.put("parentId", office.getParentId());
                }
            }
            // 新增公司信息
            for (OaSysOffice office : offices) {
                Object parentId = map.get("parentId");
                if (CheckUtil.objIsEmpty(parentId)){
                    continue;
                }
                if (office.getOfficeId().equals(Long.valueOf(parentId.toString()))){
                    map.put("parentName", office.getName());
                }
            }
            result.add(map);
        }
        IPage<Map<String, Object>> page = new Page<>();
        page.setPages(oaCWalletRecordIPage.getPages());
        page.setRecords(result);
        page.setTotal(oaCWalletRecordIPage.getTotal());
        page.setSize(oaCWalletRecordIPage.getSize());
        page.setCurrent(oaCWalletRecordIPage.getCurrent());
        return page;
    }

    /**
     * 获取全部交易类型
     * @param tag
     * @return
     */
    @Override
    public List<Map<String, Object>> selectRecordTypeAll(String tag){
        List<Map<String, Object>> result = new ArrayList<>();
        List<OaSysDict> recordTypes = oaSysDictMapper.selectList(
                Wrappers.<OaSysDict>lambdaQuery()
                        .eq(OaSysDict::getTag, tag)
                        .eq(OaSysDict::getType, "wallet_record_type"));
        for (OaSysDict recordType : recordTypes) {
            Map<String, Object> map = new HashMap<>(16);
            map.put("value", recordType.getValue());
            map.put("label", recordType.getLabel());
            result.add(map);
        }
        return result;
    }
}
